/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pt.mleiria.cipher;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import pt.mleiria.utils.MathUtils;
import static pt.mleiria.utils.MathUtils.mod;

/**
 *
 * @author manuel
 */
public class ShiftCipher {

    private final static java.util.logging.Logger LOGGER = java.util.logging.Logger.getLogger(ShiftCipher.class.getName());

    private final int A = 97;
    private final int Z = 122;
    private final Map<Integer, Character> gen = new HashMap<Integer, Character>(25);
    private String key;
    
    
    /**
     * char a = 97 char z = 122
     */
    public ShiftCipher(String key) {
        this();
        this.key = key;
    }

    public ShiftCipher() {
        for (int i = A; i <= Z; i++) {
            gen.put(i - A, (char) i);
        }
    }
    

    
    public String encrypt(final String plainText) {
        final int k = Integer.valueOf(key);
        final char[] pm = plainText.toCharArray();
        final char[] cryptoText = new char[pm.length];
        for (int i = 0; i < pm.length; i++) {
            int step0 = ((int) pm[i] - A);
            int step1 = step0 + k;
            int step2 = mod(step1, gen.size());
            int step3 = step2 + A;
            cryptoText[i] = (char) step3;
        }
        return new String(cryptoText);
    }

    /**
     *
     * @param cryptoText
     * @param k
     * @return
     */
   
    public String decrypt(final String cryptoText) {
        final int k = Integer.valueOf(key);
        final char[] ct = cryptoText.toCharArray();
        final char[] plainText = new char[ct.length];
        for (int i = 0; i < ct.length; i++) {
            int step0 = ((int) ct[i] - A);
            int step1 = step0 - k;
            int step2 = MathUtils.mod(step1, gen.size());
            int step3 = step2 + A;
            plainText[i] = (char) step3;
        }
        return new String(plainText);

    }

    /**
     * Brute force decryption
     *
     * @param cryptoMessage
     * @return
     */
    public List<String> decryptBruteForce(final String cryptoMessage) {
        final List<String> possibleResults = new ArrayList<String>(25);
        for (int i = 0; i < 25; i++) {
            this.key = String.valueOf(i);
            String res = decrypt(cryptoMessage);
            possibleResults.add(res);
            LOGGER.info(res);
        }
        return possibleResults;
    }

}
